package studio.xiaoyun.web.controller.rest;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import studio.xiaoyun.web.ErrorCode;
import studio.xiaoyun.core.exception.InvalidParameterException;
import studio.xiaoyun.core.exception.XyException;
import studio.xiaoyun.core.constant.UserType;
import studio.xiaoyun.core.dao.IUserDao;
import studio.xiaoyun.core.entity.UserEntity;
import studio.xiaoyun.security.annotation.RequireGuest;
import studio.xiaoyun.security.annotation.RequireUser;
import studio.xiaoyun.security.auth.UsernamePasswordToken;
import studio.xiaoyun.web.RestResult;
import studio.xiaoyun.web.WebException;
import studio.xiaoyun.web.resource.UserResource;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

/**
 * 用户登陆、注销
 */
@RestController
@RequestMapping("/v1")
public class LoginRestController {
    private Logger log = LoggerFactory.getLogger(LoginRestController.class);
    @Resource
    private IUserDao userDao;

    /**
     * 用户登陆
     * @param request 请求
     * @param name 用户名
     * @param password 密码
     * @param rememberMe 是否记住密码，一段时间内不用再登陆
     * @return 用户信息
     */
    @RequireGuest
    @RequestMapping(value = "/user/login",method = RequestMethod.POST)
    public RestResult userLogin(HttpServletRequest request,String name, String password,boolean rememberMe) {
        log.debug("用户登陆开始,name:{},rememberMe:{},ip:{}",name,rememberMe,request.getRemoteAddr());
        if(StringUtils.isBlank(name)){
            throw new InvalidParameterException("用户名或邮箱不能为空!");
        }
        if(StringUtils.isBlank(password)){
            throw new InvalidParameterException("密码不能为空!");
        }
        UsernamePasswordToken token = new UsernamePasswordToken(name, password);
        token.setRememberMe(rememberMe);
        token.setType(UserType.USER);
        token.setHost(request.getRemoteHost());
        UserResource userResource = login(token);
        log.debug("用户登陆成功,name:{}",name);
        return new RestResult(1L, userResource);
    }

    /**
     * 管理员登陆
     * @param request 请求
     * @param name 用户名
     * @param password 密码
     * @return 用户信息
     */
    @RequireGuest
    @RequestMapping(value = "/admin/login",method = RequestMethod.POST)
    public RestResult adminLogin(HttpServletRequest request,String name, String password) {
        log.info("管理员登陆开始,name:{},ip:{}",name,request.getRemoteAddr());
        if(StringUtils.isBlank(name)){
            throw new InvalidParameterException("用户名或邮箱不能为空!");
        }
        if(StringUtils.isBlank(password)){
            throw new InvalidParameterException("密码不能为空!");
        }
        UsernamePasswordToken token = new UsernamePasswordToken(name, password);
        token.setRememberMe(false);
        token.setType(UserType.SYSTEM);
        token.setHost(request.getRemoteHost());
        UserResource userResource = login(token);
        log.info("管理员登陆成功,name:{}",name);
        return new RestResult(1L, userResource);
    }

    /**
     * 用户注销
     */
    @RequireUser
    @RequestMapping(value = "/user/logout",method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void logout(){
        Subject subject = SecurityUtils.getSubject();
        log.debug("用户注销,userId="+subject.getPrincipal().toString());
        subject.logout();
    }

    /**
     * 管理员注销
     */
    @RequireUser
    @RequestMapping(value = "/admin/logout",method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void adminLogout(){
        Subject subject = SecurityUtils.getSubject();
        log.debug("管理员注销,userId="+subject.getPrincipal().toString());
        subject.logout();
    }

    private UserResource login(UsernamePasswordToken token){
        UserResource userResource = new UserResource();
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(token);
        } catch (UnknownAccountException uae) {  //用户名不存在
            throw new WebException("用户名不存在",ErrorCode.UNKNOWN_ACCOUNT);
        } catch (IncorrectCredentialsException ice) {  //密码错误
            throw new WebException("密码错误",ErrorCode.INCORRECT_PASSWORD);
        } catch (DisabledAccountException lae) {  //账户不可用、已删除
            throw new WebException("账户不可用",ErrorCode.DISABLED_ACCOUNT);
        }
        //登陆成功后返回用户信息到客户端
        String userId = subject.getPrincipal().toString();
        UserEntity userInfo = userDao.getById(userId);
        userResource.setUserId(userInfo.getUserId());
        userResource.setName(userInfo.getName());
        userResource.setEmail(userInfo.getEmail());
        return userResource;
    }

}
